﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using BlockeyEssentials.Input;
using BlockeyEssentials;
using Blockey.GameplayScreens;

namespace Blockey.GameObjects3D
{
    public class Skater : Person3D
    {
        public Skater(Game oGame, ControllingPlayer oPlayer, Alliance oTeamSide)
            : base(oGame, oPlayer, oTeamSide)
        {
            m_fDefaultFriction = Friction;
        }

        public override void Input(MatchScreen3D oMatchScreen)
        {
            if (m_bSkipUpdate)
            {
                m_bSkipUpdate = false;
                return;
            }

            var oHockeyMatch = oMatchScreen as HockeyGameScreen3D;
            bool oHasPuck = false;
            if (oHockeyMatch != null)
            {
                oHasPuck = HeldObjects.Contains(oHockeyMatch.Puck);
            }

            var oCanInput = Condition.IsNeutral || Condition.Name == ConditionName.Shooting;

            #region AI
            if (m_oControllingPlayer.IsAI)
            {
                if (oMatchScreen is HockeyGameScreen3D)
                {
                    #region Has Puck
                    if (this.HeldObjects.Contains(oHockeyMatch.Puck))
                    {
                        Vector3 oDestination;
                        switch (TeamSide)
                        {
                            case Alliance.Home:
                                {
                                    oDestination = Vector3.UnitX * 40;
                                    break;
                                }
                            case Alliance.Away:
                                {
                                    oDestination = Vector3.UnitX * -40;
                                    break;
                                }
                            case Alliance.Neutral:
                            default:
                                {
                                    oDestination = Vector3.Zero;
                                    break;
                                }
                        }

                        var oDirection = oDestination - Position;
                        oDirection.Z = 0;
                        if (oDirection != Vector3.Zero)
                        {
                            oDirection.Normalize();

                            Ray oRay = new Ray(Position, oDirection);
                            foreach (var oSkater in oMatchScreen.Skaters)
                            {
                                if (oSkater.TeamSide == this.TeamSide)
                                    continue;

                                var oSphere = oSkater.BaseSphere;
                                oSphere.Radius *= 2;
                                if (oRay.Intersects(oSphere) != null)
                                {
                                    if (Position.Y < oSkater.Position.Y)
                                    {
                                        oDestination = oSphere.Center - Vector3.UnitY * oSphere.Radius;
                                    }
                                    else
                                    {
                                        oDestination = oSphere.Center + Vector3.UnitY * oSphere.Radius;
                                    }
                                }

                                oDirection = oDestination - Position;
                                if (oDestination != Vector3.Zero)
                                {
                                    oDirection.Normalize();
                                }
                            }
                        }

                        Direction = oDirection;
                    }
                    #endregion

                    #region Does Not Have Puck
                    else
                    {
                        if (oCanInput)
                        {
                            Person3D oPersonWithPuck = null;
                            foreach (var oPerson in oHockeyMatch.People)
                            {
                                if (oPerson == this)
                                    continue;

                                if (oPerson.HeldObjects.Contains(oHockeyMatch.Puck))
                                {
                                    oPersonWithPuck = oPerson;
                                }
                            }

                            if (oPersonWithPuck == null)
                            {
                                float oDistance = Vector3.Distance(Position, oHockeyMatch.Puck.Position);

                                var oDestination = new Vector3(
                                    oHockeyMatch.Puck.PositionX + oHockeyMatch.Puck.VelocityX * oDistance,
                                    oHockeyMatch.Puck.PositionY + oHockeyMatch.Puck.VelocityY * oDistance,
                                    0);

                                var oDirection = (oDestination - Position);
                                if (oDirection != Vector3.Zero)
                                    oDirection.Normalize();

                                Direction = oDirection;
                            }
                            else
                            {
                                if (oPersonWithPuck.TeamSide == this.TeamSide)
                                {
                                    var oDestination = Vector3.Zero;
                                    foreach (var oTeammate in oMatchScreen.Skaters)
                                    {
                                        if (oTeammate != this && oTeammate.TeamSide == this.TeamSide)
                                        {
                                            oDestination = oTeammate.Position;
                                            break;
                                        }
                                    }

                                    oDestination.Y = Math.Sign(oDestination.Y) * 15;
                                    oDestination.X *= 0.05f;

                                    var oDirection = oDestination - Position;
                                    if (oDirection != Vector3.Zero)
                                        oDirection.Normalize();

                                    Direction = oDirection;
                                }
                                else
                                {
                                    float oDistance = Vector3.Distance(Position, oPersonWithPuck.Position);

                                    if (Velocity != Vector3.Zero)
                                    {
                                        Vector3 oDestination = oPersonWithPuck.Position;

                                        var oVeloDir = oPersonWithPuck.Velocity;
                                        oVeloDir.Z = 0;
                                        oDestination += oVeloDir * 15;

                                        if (DebugShapeRenderer.ShowLines)
                                        {
                                            DebugShapeRenderer.AddLine(oDestination, Position, Color.Red);
                                        }

                                        Vector3 oDirection = oDestination - Position;
                                        if (oDirection != Vector3.Zero)
                                        {
                                            oDirection.Z = 0;
                                            oDirection.Normalize();
                                        }

                                        Direction = oDirection;

                                        Vector2 oVelocityDirection = Vector2.Normalize(new Vector2(VelocityX, VelocityY));
                                        float oAngle = All.AngleBetweenVectors(oVelocityDirection, new Vector2(oDirection.X, oDirection.Y));
                                        if (Condition.IsNeutral && oDistance < 13 && oAngle < MathHelper.Pi * 0.25f)
                                        {
                                            this.Tackle();
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            Direction = Vector3.Zero;
                        }
                    }
                    #endregion
                }
            }
            #endregion

            #region Human
            else
            {
                bool oJustReleasedA = false;
                bool oJustReleasedB = false;
                bool oJustReleasedY = false;
                bool oJustPressedX = false;
                bool oJustPressedB = false;

                var oDirection = Vector3.Zero;

#if WINDOWS
                var oInputKey = InputManager.Keyboard;

                bool oUp = oInputKey.IsPressedOne(Keys.Up);
                bool oDown = oInputKey.IsPressedOne(Keys.Down);
                bool oLeft = oInputKey.IsPressedOne(Keys.Left);
                bool oRight = oInputKey.IsPressedOne(Keys.Right);

                if (oUp) oDirection.Y += 1;
                if (oDown) oDirection.Y -= 1;
                if (oRight) oDirection.X += 1;
                if (oLeft) oDirection.X -= 1;

                PressingA = oInputKey.IsPressedOne(Keys.F);
                PressingB = oInputKey.IsPressedOne(Keys.D);
                oJustReleasedA = oInputKey.JustReleased(Keys.F);
                oJustReleasedB = oInputKey.JustReleased(Keys.D);
                oJustReleasedY = oInputKey.JustReleased(Keys.E);
                oJustPressedX = oInputKey.JustPressed(Keys.Space);
                oJustPressedB = oInputKey.JustPressed(Keys.D);

#elif XBOX
            var oInputPad = InputManager.GamePad1;

            oDirection = new Vector3(oInputPad.LeftStick, 0);

            PressingA = oInputPad.IsPressed(Buttons.A);
            PressingB = oInputPad.IsPressed(Buttons.B);
            oJustReleasedA = oInputPad.JustReleased(Buttons.A);
            oJustReleasedB = oInputPad.JustReleased(Buttons.B);
            oJustReleasedY = oInputPad.JustReleased(Buttons.Y);
            oJustPressedX = oInputPad.JustPressed(Buttons.X);
#endif

                if (oCanInput)
                {

                    if (oDirection != Vector3.Zero)
                    {
                        oDirection.Normalize();
                        oMatchScreen.Camera.FlatDirectionRelativeToCamera(ref oDirection);
                    }

                    if (oHasPuck)
                    {
                        if (oJustReleasedA)
                        {
                            PassPuck(oMatchScreen);
                        }
                        else if (oJustPressedB)
                        {
                            Condition.ChangeType(ConditionName.Shooting, 60);
                            StartCondition(true);
                        }
                        else if (oJustReleasedB && Condition.Name == ConditionName.Shooting)
                        {
                            FinishCondition(oMatchScreen);
                        }
                    }
                    else
                    {
                        if (oJustPressedX)
                        {
                            Tackle();
                        }
                    }
                }
                else
                {
                    oDirection = Vector3.Zero;
                }

                if (oJustReleasedY)
                {
                    SwitchPlayers(oMatchScreen);
                }

                Direction = oDirection;
            }

            #endregion
        }

        public override void InputClient(Blockey.GameObjects3D.Camera3D oCamera)
        {
            var oDirection = Vector3.Zero;

            if (Condition.IsNeutral)
            {
                var oInput = InputManager.Keyboard;
                if (oInput.IsPressedOne(Keys.Left))
                    oDirection.X -= 1;
                if (oInput.IsPressedOne(Keys.Right))
                    oDirection.X += 1;
                if (oInput.IsPressedOne(Keys.Up))
                    oDirection.Y += 1;
                if (oInput.IsPressedOne(Keys.Down))
                    oDirection.Y -= 1;

                if (oDirection == Vector3.Zero)
                {
                    var oInputPad = InputManager.GamePad1;
                    oDirection = new Vector3(oInputPad.LeftStick, 0);
                }

                if (oDirection != Vector3.Zero)
                {
                    oDirection.Normalize();
                    oCamera.FlatDirectionRelativeToCamera(ref oDirection);
                }
            }

            Direction = oDirection;
        }


    }
}
